/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.isi.pegasus.planner.subworkflow.scheduler.implementation;


import edu.isi.pegasus.planner.classes.ADag;
import edu.isi.pegasus.planner.classes.PegasusBag;
import edu.isi.pegasus.planner.dax.ParADAG;
import edu.isi.pegasus.planner.subworkflow.partitioner.DAXAbstraction;
import edu.isi.pegasus.planner.subworkflow.partitioner.SiteAbstraction;
import edu.isi.pegasus.planner.subworkflow.scheduler.Scheduler;
import java.util.ArrayList;
import java.util.Iterator;

/**
 *
 * @author wchen
 */
public class Reorder extends Scheduler{
    public Reorder(ADag dag, PegasusBag bag)
    {
        super(dag,bag);
    }
    @Override
    public void siteSelector()
    {
        int siteIndex = 0;
        //calculate the dax
        String subPath = this.mBag.getPegasusProperties().getProperty("pegasus.subworkflow.argument.dir");
        //first select mDaxMap in order of dax size and then slot
        mDaxQueue.clear();
        for(Iterator it = mDaxMap.keySet().iterator(); it.hasNext();)
        {
            DAXAbstraction bigDax =((DAXAbstraction)it.next());
            //ADAG daxItem = bigDax.adag;
            double limit = bigDax.limit;
            double degree = bigDax.degree;
            if(mDaxQueue.size()==0)
            {
                mDaxQueue.add(bigDax);
                continue;
            }

            for (int i = 0; i < mDaxQueue.size() ; i ++)
            {
                //wrong totally wrong
                DAXAbstraction headDax = (DAXAbstraction)mDaxQueue.get(i);
                if(limit > headDax.limit || (limit == headDax.limit && degree > headDax.degree))
                {
                    mDaxQueue.add(i, bigDax);
                    break;
                }
                if(i == (mDaxQueue.size() -1 ))
                {
                    mDaxQueue.addLast(bigDax);
                    break;
                }

            }
        }

        ArrayList threadList  = new ArrayList<writeToFile>();
        //second select site in order of limit and slot
        for (Iterator it  = mDaxQueue.iterator(); it.hasNext();)
        {
            DAXAbstraction bigDax =((DAXAbstraction)it.next());
            ParADAG daxItem = bigDax.adag;

            String daxName = daxItem.getName() + ".xml";
            String dax_path = subPath + "/" + daxName;

            threadList.add( new writeToFile(daxItem, dax_path));
            daxItem.writeToFile(dax_path);
            addReplicaCatalog(daxName , dax_path);
            try
            {

                double limit = bigDax.size;
                int maxSlot = 0;
                SiteAbstraction selectedSite = null;
                for(int i = 0; i < mSiteIndex.size(); i++)
                {
                    SiteAbstraction site = (SiteAbstraction)mSiteIndex.get(i);
                    if (site.space < 0.95*limit) continue;
                    if (site.slot > maxSlot)
                    {
                        maxSlot = site.slot;
                        selectedSite = site;
                    }
                }
                if(selectedSite==null)
                    throw(new Exception("Size Limit Exceed"));
                else if(true)
                {
                    // which is wrong in some senses
                    // must fix it before the end
                    selectedSite.space = selectedSite.space - limit;
                }
                else
                  mSiteIndex.remove(selectedSite);

                  addDAXJob2DAG(daxName, daxItem.getName() , selectedSite.name);
                  System.out.println("dax " + daxName + " with size " + bigDax.size + " with degree " + bigDax.degree +
                          " is mapped to " + selectedSite.name + " with slot " + selectedSite.slot);



            }
            catch (Exception e)
            {

                System.out.println("no such site name\n");
            }

            siteIndex ++;

        }
        for (Iterator it = threadList.iterator(); it.hasNext();)
        {
            writeToFile wt = (writeToFile)it.next();
            wt.getDone();
        }
    }
}
